package com.codemeta.bokit.comm.kit;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.map.MapUtil;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 集合工具类
 *
 * @author 美萌:hechen
 * @date 2020/6/23
 */
public class CollKit extends CollUtil {

    /**
     * 集合不为空执行消费函数
     *
     * @param collection .
     * @param consumer   .
     */
    public static <T> void notEmpty(Iterable<T> collection, java.util.function.Consumer<Iterable<T>> consumer) {
        if (CollUtil.isNotEmpty(collection) && consumer != null) {
            consumer.accept(collection);
        }
    }

    /**
     * Iterator转换为Map，转换规则为：
     * <br> 按照keyFunc函数规则根据元素对象生成Key，元素作为值
     *
     * @param <K>     Map键类型
     * @param <V>     Map值类型
     * @param values  数据列表
     * @param keyFunc 生成key的函数
     * @return 生成的map
     * @apiNote 扩展：生成不为null的map
     */
    public static <K, V> Map<K, V> toMap(Iterable<V> values, Func1<V, K> keyFunc) {
        return IterUtil.toMap(null == values ? IterUtil.empty() : values.iterator(), MapUtil.empty(), keyFunc);
    }

    /**
     * 通过func自定义一个规则，此规则将原集合中的元素转换成新的元素，生成新的列表返回，忽略空值
     * <br> 例如提供的是一个Bean列表，通过Function接口实现获取某个字段值，返回这个字段值组成的新列表
     *
     * @param <T>        集合元素类型
     * @param <R>        返回集合元素类型
     * @param collection 原集合
     * @param func       编辑函数
     * @return 抽取后的新列表
     */
    public static <T, R> List<R> map(Iterable<T> collection, Function<? super T, ? extends R> func) {
        return CollUtil.map(collection, func, true);
    }

    /**
     * 通过func自定义一个规则，此规则将原集合中的元素转换成新的元素，生成新的列表返回，忽略空值
     * <br> 例如提供的是一个Bean列表，通过Function接口实现获取某个字段值，返回这个字段值组成的新列表
     *
     * @param <T>        集合元素类型
     * @param <R>        返回集合元素类型
     * @param collection 原集合
     * @param func       编辑函数
     * @return 抽取后的新列表
     */
    public static <T, R> Set<R> set(Iterable<T> collection, Function<? super T, ? extends R> func) {
        return new HashSet<>(map(collection, func));
    }

    /**
     * 分组列表
     *
     * @param data list
     * @param fun  .
     * @param <T>  .
     * @param <R>  .
     * @return .
     */
    public static <T, R> Map<R, List<T>> group(List<T> data, Function<T, R> fun) {
        return CollUtil.isEmpty(data) ? Collections.emptyMap()
            : data.stream().collect(Collectors.groupingBy(fun));
    }
}